package com.carl.lambda.streamAPI.lambda01;


import com.carl.lambda.simpleLambda.lambda1.Employee;
import org.junit.Test;

import java.util.*;
import java.util.stream.Stream;

/*
 * 一、Stream API 的操作步骤：
 *
 * 1. 创建 Stream
 *
 * 2. 中间操作
 *
 * 3. 终止操作(终端操作)
 */
public class TestStreamAPI2 {


    List<Employee> employees = Arrays.asList(
            new Employee("张三",18,99.99),
            new Employee("李四",28,999.99),
            new Employee("王五",32,9999.99),
            new Employee("赵六",48,9999.99),
            new Employee("钱七",58,9999.99),
            new Employee("钱七",58,9999.99),
            new Employee("钱七",58,9999.99)
    );
    /*
	  1. 筛选与切片
		filter——接收 Lambda ， 从流中排除某些元素。
		limit——截断流，使其元素不超过给定数量。
		skip(n) —— 跳过元素，返回一个扔掉了前 n 个元素的流。若流中元素不足 n 个，则返回一个空流。与 limit(n) 互补
		distinct——筛选，通过流所生成元素的 hashCode() 和 equals() 去除重复元素
	 */
      //内部迭代:迭代操作有Stream Api 完成
      @Test
      public void test01(){  //filter——接收 Lambda ， 从流中排除某些元素。
          //中间操作
          Stream<Employee> employeeStream = employees.stream()
                  .filter((e) -> e.getAge() > 35);
          //终止操作 一次性执行全部内容,即"惰性求值"
          employeeStream.forEach(System.out::println);
      }
      //外部迭代 自己写迭代代码
    @Test
    public void test02(){
        Iterator<Employee> iterator = employees.iterator();
        while (iterator.hasNext()){
            System.out.println(iterator.next());
        }
    }

    //limit——截断流，使其元素不超过给定数量。
    @Test
    public void test03(){
        Stream<Employee> limit = employees.stream().filter(e -> e.getAge() > 35).limit(1);
        limit.forEach(System.out::println);
    }

    //skip(n) —— 跳过元素，返回一个扔掉了前 n 个元素的流。若流中元素不足 n 个，则返回一个空流。与 limit(n) 互补
    @Test
    public void test04(){
          employees.stream()
                  .filter(e->e.getSalary()>9000)
                  .skip(1) //加入有三个元素  扔掉第一个元素
                  .forEach(System.out::println);
    }

    //distinct——筛选，通过流所生成元素的 hashCode() 和 equals() 去除重复元素
    //因为该方法是通过 hashCode() 和 equals() 方法实现去重,所以实体类里必须重写 hashCode() 和 equals()这两个方法
    @Test
    public void test05(){
          employees.stream()
                  .filter(e->e.getSalary()>9000)
                  .distinct()
                  .forEach(System.out::println);
    }


    //2. 中间操作
	/*
		映射
		map——接收 Lambda ， 将元素转换成其他形式或提取信息。接收一个函数作为参数，该函数会被应用到每个元素上，并将其映射成一个新的元素。
		flatMap——接收一个函数作为参数，将流中的每个值都换成另一个流，然后把所有流连接成一个流
	 */
    @Test
    public void test06(){
        List<String> list = Arrays.asList("aaa","bbb","ccc","ddd");
        list.stream()
                .map(String::toUpperCase)
                .forEach(System.out::println);

        //需求:提取员工姓名
         employees.stream()
                .map(Employee::getName)
                 .forEach(System.out::println);

    }

    //flatMap——接收一个函数作为参数，将流中的每个值都换成另一个流，然后把所有流连接成一个流
    @Test
    public void test07(){
        List<String> list = Arrays.asList("aaa","bbb","ccc","ddd");

        list.stream()
                .flatMap(TestStreamAPI2::filterCharacter)
                .forEach(System.out::println);
    }

    public static Stream<Character> filterCharacter(String str){
        List<Character> list = new ArrayList<>();

        for (Character ch : str.toCharArray()) {
            list.add(ch);
        }

        return list.stream();
    }

    /**
     * 总结: map和flatmap的区别就相当于集合中add(Object obj)和addAll(Collection c)的区别一样
     */
    @Test
    public void test08(){
        List<String> list = Arrays.asList("aaa","bbb","ccc","ddd");
        List list2 =new ArrayList();

        list2.add(1);
        list2.add(2);
        list2.addAll(list);//[1, 2, aaa, bbb, ccc, ddd]
        System.out.println(list2); //[1, 2, aaa, bbb, ccc, ddd]

        list2.add(list); //[1, 2, [aaa, bbb, ccc, ddd]]
        System.out.println(list2);

    }


   /*  3.排序
		sorted()——自然排序 (Comparable)
		sorted(Comparator com)——定制排序(Comparator)
	 */
    @Test
    public void test09(){ //sorted()——自然排序 (Comparable)
        List<String> list = Arrays.asList("ddd","ccc","aaa","bbb");
        list.stream().sorted().forEach(System.out::println);
    }

    @Test
    public void test10(){
        List<Employee> employees = Arrays.asList(
                new Employee("张三",78,99.99),
                new Employee("李四",28,999.99),
                new Employee("王五",18,9999.99),
                new Employee("赵六",30,9999.99),
                new Employee("钱七",21,9999.99),
                new Employee("钱七",58,9999.99),
                new Employee("钱七",58,9999.99)
        );

        //按年龄排序,如果年龄一样就按姓名排序
        employees.stream().sorted((e1,e2)->{
            if (Objects.equals(e1.getAge(), e2.getAge())){
                return e1.getName().compareTo(e2.getName());
            }else {
                return -e1.getAge().compareTo(e2.getAge());
            }
        }).forEach(System.out::println);
    }












}
